# -*- coding: utf-8 -*-
import json
import time
import cv2
import ddddocr
import requests
import execjs
from loguru import logger
import track
from gap import SlideCrack
import random


class WyCaptcha:
    def __init__(self):
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
        }
        self.exe_d = self.get_exe_d()
        self.exe = self.get_exe()
        self.proxies = {
            "http": None,
            "https": None
        }
        self.tracks_list = [
            ['5,0,141', '8,0,150', '13,0,157', '16,0,165', '20,0,173', '23,0,182', '26,0,189', '28,0,198', '32,0,206', '35,0,213', '37,0,221', '39,0,229', '42,0,237', '45,0,245', '47,0,254', '50,0,261', '52,0,269', '54,0,277', '56,0,285', '60,0,293', '63,0,301', '67,0,308', '72,0,317', '76,0,325', '79,0,333', '81,0,341', '84,0,349', '85,0,357', '87,0,366', '89,0,373', '90,0,381', '91,0,391', '93,0,399', '93,0,407', '95,0,416', '97,0,423', '98,0,439', '99,0,448', '100,0,456', '101,0,462',
                '103,0,471', '105,0,479', '107,0,487', '110,0,495', '112,0,503', '115,0,511', '119,0,519', '123,0,527', '125,0,535', '127,0,543', '128,0,551', '129,0,559', '130,0,576', '131,0,584', '131,0,591', '133,0,599', '134,0,607', '135,0,615', '137,0,624', '139,0,631', '141,0,639', '142,0,647', '144,0,655', '145,0,663', '147,0,672', '147,0,681', '149,0,689', '150,0,699', '152,0,706', '153,0,713', '155,0,722', '157,0,729', '159,0,737', '161,0,748', '162,0,754', '163,1,761', '164,1,769',
                '165,1,776', '166,1,785', '167,1,793', '169,1,801', '173,1,809', '177,2,817', '181,2,826', '183,2,834', '187,2,841', '188,3,851', '189,3,857', '191,3,866', '191,3,881'],
            ['6,0,82', '10,0,90', '16,0,95', '23,0,105', '32,0,111', '39,0,120', '46,0,127', '51,0,135', '56,0,143', '61,0,151', '65,0,159', '70,-2,168', '75,-2,187', '77,-2,194', '78,-2,201', '80,-2,210', '82,-2,218', '84,-2,226', '90,-3,234', '93,-3,242', '97,-3,250', '101,-3,258', '104,-3,266', '108,-3,274', '111,-3,281', '112,-3,290', '114,-3,298', '115,-3,306', '117,-3,314', '119,-3,321', '121,-3,329', '127,-3,337', '132,-3,345', '138,-3,353', '144,-3,361', '146,-3,370', '150,-2,377',
                '155,-2,386', '157,-2,393', '158,-2,402', '159,-2,409', '158,-2,791', '157,-2,797', '156,-2,807', '156,-1,813', '155,-1,822', '154,-1,847', '154,-1,853', '153,-1,861', '152,0,869', '152,0,885', '151,0,902', '150,0,926', '150,0,1000']
        ]

    def get_exe_d(self):
        with open("watchman.js", "r", encoding="utf-8") as f:
            js_data_d = f.read()
        exe_d = execjs.compile(js_data_d)
        return exe_d

    def get_exe(self):
        with open("core.js", "r", encoding="utf-8") as f:
            js_data = f.read()
        exe = execjs.compile(js_data)
        return exe

    def get_d(self):
        url = "https://ac.dun.163.com/v3/d"
        data = {
            "d": self.exe_d.call("get_d_d"),
            "v": "33d41777",
            "cb": "__wmjsonp_a5de29f"
        }
        response = requests.post(url=url, headers=self.headers, data=data, proxies=self.proxies)
        # logger.info(f"d接口响应====>>>{response.text}")
        resp_str = response.text.split("(")[-1].split(")")[0]
        str_to_list = json.loads(resp_str)
        return {"WM_TID": str_to_list[2], "WM_DID": str_to_list[3]}

    def get_config(self):
        url = "https://c.dun.163.com/api/v2/getconf"
        params = {
            "referer": "https://dun.163.com/trial/jigsaw",
            "zoneId": "",
            "id": "07e2387ab53a4d6f930b8d9a9be71bdf",
            "ipv6": "false",
            "runEnv": "10",
            "iv": "4",
            "type": "2",
            "loadVersion": "2.4.0",
            "callback": "__JSONP_cldynjj_0"
        }
        response = requests.get(url=url, headers=self.headers, params=params, proxies=self.proxies)
        data = response.text.split("(")[-1].split(")")[0]
        str_to_dict = json.loads(data)
        val = str_to_dict.get("data").get("dt")
        return val

    def get_b(self, WM_TID, WM_DID):
        url = "https://ac.dun.163.com/v3/b"
        data = {
            "d": self.exe_d.call("get_b_d", WM_TID, WM_DID),
            "v": "33d41777",
            "cb": "__wmjsonp_2b1bc53"
        }
        response = requests.post(url=url, headers=self.headers, data=data, proxies=self.proxies)
        # logger.info(f"b请求======>>>>{response.text}")

    def get_referer(self, WM_DID, dt):
        url = "https://c.dun.163.com/api/v3/get"
        acToken = self.exe_d.call("get_actoken", WM_DID)
        # logger.info(f"acToken======>>>{acToken}")
        params = {
            "referer": "https://dun.163.com/trial/jigsaw",
            "zoneId": "CN31",
            "dt": dt,
            "acToken": acToken,
            "id": "07e2387ab53a4d6f930b8d9a9be71bdf",
            "fp": self.exe.call("get_fp"),
            "https": "true",
            "type": "2",
            "version": "2.27.2",
            "dpr": "1",
            "dev": "1",
            "cb": self.exe.call("get_cb"),
            "ipv6": "false",
            "runEnv": "10",
            "group": "",
            "scene": "",
            "lang": "zh-CN",
            "sdkVersion": "undefined",
            "iv": "4",
            "width": "320",
            "audio": "false",
            "sizeType": "10",
            "smsVersion": "v3",
            "token": "3b8e1865e965439d8630fa9540e37260",
            "callback": self.exe.call("get_JSONP")
        }
        response = requests.get(url=url, headers=self.headers, params=params, proxies=self.proxies)
        # logger.info(f"get接口响应=====>>>{response.text}")
        data = response.text.split("(")[-1].split(")")[0]
        str_to_dict = json.loads(data)
        bg_url = str_to_dict.get("data").get("bg")[0]
        response = requests.get(url=bg_url, headers=self.headers, proxies=self.proxies).content
        with open("./images/bg.jpg", "wb") as f:
            f.write(response)
        front_url = str_to_dict.get("data").get("front")[0]
        response = requests.get(url=front_url, headers=self.headers, proxies=self.proxies).content
        with open("./images/front.jpg", "wb") as f:
            f.write(response)
        token = str_to_dict.get("data").get("token")
        return token

    def _zoom_track(self, distance):
        tracks = random.choice(self.tracks_list)
        old_distance = int(tracks[-1].split(",")[0])
        scale = distance / old_distance
        new_track = []
        for track in tracks:
            new_track.append(",".join([str(int(int(track.split(",")[0]) * scale)), track.split(",")[1], track.split(",")[2]]))
        return new_track

    def get_check(self, data, token, dt):
        url = "https://c.dun.163.com/api/v3/check"
        params = {
            "referer": "https://dun.163.com/trial/jigsaw",
            "zoneId": "CN31",
            "dt": dt,
            "id": "07e2387ab53a4d6f930b8d9a9be71bdf",
            "token": token,
            "acToken": "undefined",
            "data": data,
            "width": "320",
            "type": "2",
            "version": "2.27.2",
            "cb": self.exe.call("get_cb"),
            "extraData": "",
            "bf": "0",
            "runEnv": "10",
            "sdkVersion": "undefined",
            "iv": "4",
            "callback": self.exe.call("get_JSONP")
        }
        response = requests.get(url=url, headers=self.headers, params=params, proxies=self.proxies)
        data = response.text.split("(")[-1].split(")")[0]
        str_to_dict = json.loads(data).get("data")
        return str_to_dict

    def captcha(self):
        # 补dt 不知道是否用到
        dt = self.get_config()

        # d接口
        d_data = self.get_d()
        WM_TID = d_data.get("WM_TID")
        WM_DID = d_data.get("WM_DID")

        # b接口 WM_TID, WM_DID
        self.get_b(WM_TID, WM_DID)

        # get
        token = self.get_referer(WM_DID, dt)
        # logger.info(f"token值=======>>>{token}")
        left = SlideCrack("./images/front.jpg", "./images/bg.jpg", "./images/result.jpg").discern()
        # logger.info(f"left值=======>>>{left}")

        # check
        tracks = self._zoom_track(left)
        data = self.exe.call("get_data", tracks, token, left)
        # logger.info(f"check data值=======>>>{data}")
        return self.get_check(data, token, dt)


if __name__ == '__main__':
    count = 0
    for i in range(10):
        wy = WyCaptcha()
        ret = wy.captcha()
        if ret.get("validate") != 0:
            logger.success(ret)
            count += 1
    logger.success(f"成功率======>>>{(10 / count) * 100}%")
